package main

import (
	"fmt"
	"math"
)

func main() {
	// 求和
	sum := sum(1, 2)
	fmt.Printf("两个数的和是：%d \n", sum)

	// 调换两个参数
	var x = "Google"
	var y = "Baidu"
	x, y = swapValue(x, y)
	fmt.Println("x = " + x + ", y = " + y)

	// 调换两个参数
	var n int = 1
	var m int = 100
	swapQuote(&n, &m)
	fmt.Printf("n = %d, m = %d \n", n, m)

	// 函数作为参数
	funcAsParam()

	// 闭包
	/* nextNumber 为一个函数，函数 i 为 0 */
	nextNumber := closePackage()

	/* 调用 nextNumber 函数，i 变量自增 1 并返回 */
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())

	/* 创建新的函数 nextNumber1，并查看结果 */
	nextNumber1 := closePackage()
	fmt.Println(nextNumber1())
	fmt.Println(nextNumber1())

}

/*
	闭包是匿名函数，可在动态编程中使用
*/
func closePackage() func() int {
	i := 0
	return func() int {
		i += 1
		return i
	}
}

/*
	函数定义后可作为另外一个函数的实参数传入
*/
func funcAsParam() {
	getSquareRoot := func(x float64) float64 {
		return math.Sqrt(x)
	}
	fmt.Printf("根号9 = %f", getSquareRoot(9))
}

/*
	两个数的和
*/
func sum(num1, num2 int) int {
	return num1 + num2
}

/**
值传递 值传递是指在调用函数时将实际参数复制一份传递到函数中，这样在函数中如果对参数进行修改，将不会影响到实际参数。
将两个参数调换
*/
func swapValue(x, y string) (string, string) {
	return y, x
}

/*
	引用传递
	引用传递是指在调用函数时将实际参数的地址传递到函数中，那么在函数中对参数所进行的修改，将影响到实际参数。
	将两个参数调换
*/
func swapQuote(x *int, y *int) {
	var temp int
	temp = *x /* 保存 x 地址上的值 */
	*x = *y   /* 将 y 值赋给 x */
	*y = temp /* 将 temp 值赋给 y */
}
